/**
* Copyright (c) By zengqh.
*
* This program is just for fun or demo, in the hope that it  
* will be useful, you can redistribute it and/or modify freely.
*
* Time: 2013/02/17
* File: enn_math_def.h
* Blog: http://www.cnblogs.com/zengqh/
**/

#pragma once

#include <enn_platform_headers.h>
#include "enn_random.h"

#define ENN_PI				(3.14159265358979323846)
#define ENN_TWO_PI			(6.28318530717958647692)
#define ENN_HALF_PI			(1.57079632679489661923)
#define ENN_DEGTORAD		(0.01745329251994329577)
#define ENN_RADTODEG		(57.2957795130823208768)
#define ENN_EPSILON			(0.000001f)
#define ENN_MIN_NEARPLANE	(0.01f)
#define ENN_MIN_INT			(0x80000000)
#define ENN_MAX_INT			(0x7fffffff)
#define ENN_MIN_UNSIGNED	(0x0)
#define ENN_MAX_UNSIGNED	(0xffffffff)

namespace enn
{

/** Intersection test result. */
enum Intersection
{
	OUTSIDE,
	INTERSECTS,
	INSIDE
};

/** Linear interpolation between two float values. */
inline float Lerp(float lhs, float rhs, float t) { return lhs * (1.0f - t) + rhs * t; }

/** Return the smaller of two floats. */
inline float Min(float lhs, float rhs) { return lhs < rhs ? lhs : rhs; }

/** Return the larger of two floats. */
inline float Max(float lhs, float rhs) { return lhs > rhs ? lhs : rhs; }

/** Return absolute value of a float. */
inline float Abs(float value) { return value >= 0.0f ? value : -value; }

/** Clamp a float to a range. */
inline float Clamp(float value, float min, float max)
{
	if (value < min)
		return min;
	else if (value > max)
		return max;
	else
		return value;
}

/** Check whether two floating point values are equal within accuracy. */
inline bool Equals(float lhs, float rhs) { return lhs + ENN_EPSILON >= rhs && lhs - ENN_EPSILON <= rhs; }

/** Return the smaller of two integers. */
inline int Min(int lhs, int rhs) { return lhs < rhs ? lhs : rhs; }

/** Return the larger of two integers. */
inline int Max(int lhs, int rhs) { return lhs > rhs ? lhs : rhs; }

/** Return absolute value of an integer. */
inline int Abs(int value) { return value >= 0 ? value : -value; }

/** Clamp an integer to a range. */
inline int Clamp(int value, int min, int max)
{
	if (value < min)
		return min;
	else if (value > max)
		return max;
	else
		return value;
}

/** Check whether an unsigned integer is a power of two. */
inline bool IsPowerOfTwo(unsigned value)
{
	if (!value)
		return true;
	while (!(value & 1))
		value >>= 1;
	return value == 1;
}

/** Round up to next power of two. */
inline unsigned NextPowerOfTwo(unsigned value)
{
	unsigned ret = 1;
	while (ret < value && ret < 0x80000000)
		ret <<= 1;
	return ret;
}

/** Return a random float between 0.0 (inclusive) and 1.0 (exclusive.) */
inline float Random() { return Rand() / 32768.0f; }

/** Return a random float between 0.0 and range, inclusive from both ends. */
inline float Random(float range) { return Rand() * range / 32767.0f; }

/** Return a random integer between 0 and range - 1. */
inline int Random(int range) { return (Rand() * (range - 1) + 16384) / 32767; }

inline uint32 FloatToUint32(float f)
{
	return *(reinterpret_cast<uint32*>(&f));
}

inline float Uint32ToFloat(uint32 n)
{
	return *(reinterpret_cast<float*>(&n));
}

}